package com.service.sys;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ZipUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.common.base.BaseService;
import com.common.util.UpDownUtil;
import com.common.util.WordPDFUtil;
import com.entity.sys.SysDept;
import com.entity.sys.SysRole;
import com.entity.sys.SysUser;
import com.entity.sys.SysUserRole;
import com.entity.sys.query.SysQuery;
import com.entity.sys.query.SysUserVo;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.mapper.sys.SysUserMapper;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 用户信息 服务实现类
 */
@Service
public class SysUserService extends BaseService<SysUserMapper, SysUser>{

    @Resource
    private SysDeptService sysDeptService;
    @Resource
    private SysUserRoleService sysUserRoleService;
    @Resource
    private SysRoleService sysRoleService;

    public SysUser getUser(String id,String name){
        Map<String,Object> map = new HashMap<>();
        if (StrUtil.isNotBlank(id)){
            map.put("id",id);
        }
        if (StrUtil.isNotBlank(name)){
            map.put("name",name);
        }
        SysUser user = baseMapper.getById(map);
        List<SysUserRole.UserRoleVo> roleList = sysUserRoleService.getRoleByUserId(user.getId());
        user.setRoleList(roleList);
        List<String> collect = roleList.stream().map(SysUserRole.UserRoleVo::getRoleId).collect(Collectors.toList());
        user.setRoleIds(collect.toArray(new String[0]));
        return user;
    }

    /**
     * 用户列表分页
     */
    public PageInfo<SysUser> page(SysQuery queryVo) {
        PageHelper.startPage(queryVo.getPageNum(),queryVo.getPageSize());
        Map<String, Object> map = sysParams(queryVo);
        String sqlStr = queryApplyScope("b.id","a.id", 1);
        if (StrUtil.isNotBlank(sqlStr)){
            map.put("dataScope",sqlStr);
        }
        List<SysUser> list = baseMapper.page(map);
        return new PageInfo<>(list);
    }

    /**
     * 校验用户名是否唯一
     */
    public boolean checkUserNameAndPhone(String userName,String id) {
        QueryWrapper<SysUser> queryWrapper = new QueryWrapper();
        if (StrUtil.isNotBlank(userName)){
            queryWrapper.eq("user_name",userName);
        }
        if (StrUtil.isNotBlank(id)){
            queryWrapper.ne("id",id);
        }
        int count = baseMapper.selectCount(queryWrapper);
        return count > 0 ? true : false;
    }

    /**
     * 新增角色部门信息
     */
    public void insertUserRole(String id, String[] roleIds) {
        // 删除角色与部门关联
        QueryWrapper<SysUserRole> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(SysUserRole::getUserId,id);
        sysUserRoleService.remove(queryWrapper);
        List<SysUserRole> list = new ArrayList<>();
        // 新增用户与角色关联
        for (String roleId : roleIds) {
            list.add(new SysUserRole(id,roleId));
        }
        if (!list.isEmpty()){
            sysUserRoleService.insertBatch(list);
        }
    }

    private void setDataScope(Map<String,String> queryDataScope,List<String> collect,SysUser user){
        if (collect.contains("2")){ // 获取所在部门及子部门的id和name
            Map<String, String> child = sysDeptService.getChildIdAndName(user.getDeptId());
            if (child != null){
                queryDataScope.put("deptAndSubId",child.get("id"));
                queryDataScope.put("deptAndSubName",child.get("name"));
            }
            queryDataScope.put("deptId",user.getDeptId());
            queryDataScope.put("deptName",user.getDeptName());
        }else if (collect.contains("3")){ // 获取所在部门的id和name
            queryDataScope.put("deptId",user.getDeptId());
            queryDataScope.put("deptName",user.getDeptName());
        }else { // 仅本人数据：获取当前用户id，以及获取所在部门的id和name
            queryDataScope.put("createBy",user.getId());
            queryDataScope.put("deptId",user.getDeptId());
            queryDataScope.put("deptName",user.getDeptName());
        }
    }

    /**
     * 设置用户的数据范围查询条件：
     * 问题：关于部门id和name，既然设置了id为什么还要设置name呢？
     * 解释：像用户与部门、角色与部门之间的关联用的是部门id关联。
     *      但是因为我自己这边的业务的原因，有一些表数据的所属部门并不是用部门id来进行关联的，而是直接用部门名称关联，
     *      为了方便以后加业务，拓展，所以我这里把部门名称也一起设置了，这个可以根据实际情况选择要不要设置部门名称，
     */
    public void setDataScope(SysUser user){
        Map<String,String> queryDataScope = new HashMap<>();
        List<SysUserRole.UserRoleVo> roleList = user.getRoleList();
        List<String> collect = roleList.stream().map(t -> String.valueOf(t.getDataScope())).collect(Collectors.toList());
        // 1-4这几个数字里，数字从小到大，数据范围是越来越小的，比如1包含了2、3、4的范围，2包含了3、4的范围，以此类推。
        // 所以只要在用户拥有的数据范围里面，直接取最小的那个数字的范围就行，其他数字的范围就不用取了。
        if (collect.contains("1")) {
            return;
        }
        if (collect.contains("5")){// 自定义数据：根据角色id获取关联的部门id
            // 包含了5则是取其他数字的数据范围和5的数据范围的并集
            for (int i = 0; i < collect.size(); i++) {
                if ("5".equals(collect.get(i))){
                    String roleId = roleList.get(i).getRoleId();
                    SysQuery query = new SysQuery();
                    query.setId(roleId);
                    List<String> idList = sysDeptService.selectIdListByRoleId(query);   // 根据角色id获取部门id
                    List<SysDept> deptList = sysDeptService.listByIds(idList);  // 根据部门id查询部门列表
                    if (!deptList.isEmpty()) {
                        List<String> c = deptList.stream().map(SysDept::getName).collect(Collectors.toList());
                        queryDataScope.put("customName",StrUtil.join(",", c));
                    }
                    queryDataScope.put("customId",StrUtil.join(",", idList));
                }
            }
            queryDataScope.put("dataScope","5");
            setDataScope(queryDataScope,collect,user);
        }else {
            setDataScope(queryDataScope,collect,user);
        }
        user.setQueryDataScope(queryDataScope);
    }

    /**
     * 用户列表
     * @param exportPath 导出为word/pdf时，头像单独作为附件一起导出的路径（不需要可以去掉这个参数）
     */
    public List<SysUserVo> list(SysQuery queryVo,String exportPath) {
        Map<String, Object> map = sysParams(queryVo);
        String sqlStr = queryApplyScope("b.id","a.id", 1);
        if (StrUtil.isNotBlank(sqlStr)){
            map.put("dataScope",sqlStr);
        }
        String path = System.getProperty("user.dir")+"/"; // 获取当前项目路径
        List<SysUserVo> list = baseMapper.list(map);
        for (SysUserVo vo : list) {
            if (StrUtil.isNotBlank(vo.getDataScope())){
                String dataScope = vo.getDataScope().replace("1","所有数据").replace("2","所在部门及子部门数据")
                        .replace("3","所在部门数据").replace("4","仅本人数据").replace("5","自定义数据");
                vo.setDataScope(dataScope);
            }
            if (StrUtil.isNotBlank(vo.getPicture())){
                vo.setPicture(path+vo.getPicture()); // 获取头像的绝对路径
                vo.setPhoto(UpDownUtil.getImageBase64String(vo.getPicture(),true)); // 设置头像的base64编码
                FileUtil.copy(vo.getPicture(),exportPath,true); // 将源路径的图片复制到导出的路径中
            }
        }
        return list;
    }

    /**
     * 导出word或pdf为压缩包
     * 这里因为把word里面的图片页一起单独作为文件附件下载下来了，所以要打包成一个压缩包；
     * 如果不用把图片单独下载或没有其他附件，就不用打包成压缩包，而是直接下载单个word或pdf。
     */
    public File exportWordOrPdfZIP(SysQuery queryVo,String code,boolean isPdf) throws IOException {
        String path = System.getProperty("user.dir")+"/"; // 获取当前项目路径
        File file = new File(path+"temp"+"/"+code); // 获取临时的根路径
        if (!file.exists()) file.mkdirs(); // 判断文件路径是否存在
        System.out.println("保存的路径=========>>>>>>>"+file.getPath());
        String wordName = file.getPath()+"/"+ code +".doc"; // 设置导出的word的全路径名称
        exportFormatWord(queryVo,file.getAbsolutePath(),code,wordName); // 生成word
        if (isPdf){ //生成pdf
            String pdfName = file.getPath()+"/"+ code +".pdf"; // 设置导出的pdf的全路径名称
            WordPDFUtil.wordConvertPdf(wordName,pdfName); // 将word转成pdf
            FileUtil.del(wordName);// 将word文件删除
        }
        File zip = ZipUtil.zip(file); // 压缩包
        return zip;
    }

    /**
     * 生成word
     */
    public void exportFormatWord(SysQuery query,String path,String code,String wordName){
        //需要导出的模板的数据
        Map<String,Object> dataMap = new HashMap<>();
        // 角色列表按照自己的业务逻辑自行查询
        List<String> roleList = sysRoleService.list().stream().map(SysRole::getRoleName).collect(Collectors.toList());
        dataMap.put("roleList",roleList); // 所有角色
        dataMap.put("roleOther","角色对应数据范围，分别有：所有数据、所在部门及子部门数据、所在部门数据、仅本人数据、自定义数据"); // 角色其他说明
        dataMap.put("userList",list(query,path)); // 用户列表（按照自己的逻辑自行查询）

        //第一个图片list
        List<Map<String,String>> pictureList1 = new ArrayList<>();
        pictureList1.add(UpDownUtil.getImageBase64String("E:\\document\\图片\\剑网三\\儒风.jpg",false));
        pictureList1.add(UpDownUtil.getImageBase64String("E:\\document\\图片\\剑网三\\雪河.jpg",false));
        pictureList1.add(UpDownUtil.getImageBase64String("E:\\document\\图片\\剑网三\\破虏.jpg",false));
        //第二个图片list
        List<Map<String,String>> pictureList2 = new ArrayList<>();
        pictureList2.add(UpDownUtil.getImageBase64String("E:\\document\\图片\\剑网三\\风雷.jpg",false));
        pictureList2.add(UpDownUtil.getImageBase64String("E:\\document\\图片\\剑网三\\驰冥.jpg",false));
        pictureList2.add(UpDownUtil.getImageBase64String("E:\\document\\图片\\剑网三\\破虏.jpg",false));

        // pictureList1、pictureList2 这两个的图片没有像用户头像一样，单独作为附件下载。
        // 如果有其他附件的话也像头像一样，直接用源文件复制到导出的路径就行，就可以一起打包成zip了。
        //将处理好的数据，放到模板数据中
        dataMap.put("pictureList1",pictureList1);
        dataMap.put("pictureList2",pictureList2);
        dataMap.put("code",code); // 设置页眉
        //生成word文件到临时文件夹下
        WordPDFUtil.exportWord(dataMap,"用户档案.ftl",wordName);
    }
}
